package com.example.concurrency.chapter6.lock;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

public class FIFOMutex {
    // 使用CAS算法的同步队列
    private Queue<Thread> queue = new ConcurrentLinkedDeque<>();
    private AtomicBoolean locked = new AtomicBoolean(false);

    // 锁获取失败使阻塞线程，不可中断
    public void lock(){
        Thread t = Thread.currentThread();
        queue.add(t);
        boolean isInterrupted = false;
        while (queue.peek() != t || !locked.compareAndSet(false, true)){
            LockSupport.park();
            if (Thread.interrupted())
                isInterrupted = true;
        }
        // 该类需要一个变量表示锁状态，否则线程被加入到队列后可能很快被移除，导致每个线程都是队列首元素
        queue.remove();
        // 恢复中断
        if (isInterrupted)
            t.interrupt();

    }

    public void unlock(){
        locked.set(false);
        Thread t = queue.peek();
        LockSupport.unpark(t);
    }

    public static void main(String[] args) {
        FIFOMutex mutex = new FIFOMutex();
        for (int i = 0; i < 10; i++){
            new Thread(new Task(mutex)).start();
        }
    }

   static class Task implements Runnable{
        private FIFOMutex mutex;

        public Task(FIFOMutex mutex) {
            this.mutex = mutex;
        }

        @Override
        public void run() {
            mutex.lock();
            try {
                System.out.println("线程【" + Thread.currentThread().getName() + "】取得锁");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                mutex.unlock();
            }
        }
    }

}
